<template>
  <div class="w-full h-[calc(100vh-64px)] flex flex-col lg:flex-row gap-4 p-3 lg:p-6 overflow-hidden">
    <RoleSidebar 
        :name="displayedName" 
        :avatar="displayedAvatar" 
        :tags="computedTags" 
        :intro="role.intro as any" 
        :isFavorited="role.isFavorited as any" 
        :id="role.id as any"
        @setBackground="handleSetBackground"
        @removeBackground="handleRemoveBackground"
      />

      <section class="flex-1 min-w-0 h-full">
        <div 
          :class="['bg-[var(--color-surface)] rounded-[var(--radius-lg)] shadow-[var(--shadow-sm)] ring-1 ring-[var(--color-border)] p-4 lg:p-5 text-[var(--color-text)] relative chat-container h-full flex flex-col', { 'drag-over': isDragOver }]"
          :style="{ backgroundImage: backgroundImage }"
          @dragover="handleDragOver"
          @drop="handleDrop"
          @dragleave="handleDragLeave"
          @dblclick="handleDoubleClickRemove"
        >
          
          <!-- <ChatHeader :name="role.name" /> -->
          <div class="flex-1 overflow-y-auto pr-1 pb-24 lg:pb-28" data-scroll-container>
            <MessageList 
              v-if="role.id"
              ref="messageListRef"
              :roleName="displayedName" 
              :roleAvatar="displayedAvatar"
              @retry="handleRetry"
            />
            <!-- 角色信息加载中的占位 -->
            <div v-else class="flex-1 flex items-center justify-center">
              <div class="text-center">
                <div class="inline-block animate-spin rounded-full h-8 w-8 border-b-2 border-[#635BFF] mb-4"></div>
                <p class="text-gray-500">加载角色信息中...</p>
              </div>
            </div>
          </div>
          <!-- 相对卡片的定位，左右与内容边缘对齐 -->
          <div class="absolute left-4 right-4 lg:left-5 lg:right-5 bottom-4 z-40">
            <Composer 
              :isLoading="isLoading"
              @send="handleSendMessage"
              @openVoice="showVoiceOverlay = true"
            />
          </div>
        </div>
      </section>
      <VoiceCallOverlay 
            v-model="showVoiceOverlay" 
            :status="overlayStatus" 
            :baseURL="voiceBaseURL" 
            :chatId="String(role.id)" 
            @hangup="onOverlayHangup" 
          />
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
import { useRoute } from 'vue-router'
import RoleSidebar from '@/components/detail/RoleSidebar.vue'
import MessageList from '@/components/detail/MessageList.vue'
import Composer from '@/components/detail/Composer.vue'
import VoiceCallOverlay from '@/components/detail/VoiceCallOverlay.vue'
import { chatService } from '@/utils/chatService'
import type { ChatResponse } from '@/api/interface'

const route = useRoute()
const messageListRef = ref<InstanceType<typeof MessageList>>()
const isLoading = ref(false)
const showVoiceOverlay = ref(false)
const overlayStatus = ref<'listening' | 'recognizing' | 'speaking'>('recognizing')

// 背景图片状态
const backgroundImageUrl = ref<string>('')
const isDragOver = ref(false)

const onOverlayHangup = () => {
  showVoiceOverlay.value = false
}

// 拖拽处理函数
const handleDragOver = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = true
  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'copy'
  }
}

const handleDrop = (event: DragEvent) => {
  event.preventDefault()
  isDragOver.value = false
  
  if (event.dataTransfer) {
    try {
      const jsonData = event.dataTransfer.getData('application/json')
      if (jsonData) {
        const data = JSON.parse(jsonData)
        // 只处理头像拖拽，忽略背景拖拽
        if (data.type === 'avatar' && data.imageUrl) {
          backgroundImageUrl.value = data.imageUrl
          console.log('设置背景图片:', data.imageUrl)
        }
      } else {
        // 如果没有JSON数据，尝试获取文本数据
        const imageUrl = event.dataTransfer.getData('text/plain')
        if (imageUrl) {
          backgroundImageUrl.value = imageUrl
          console.log('设置背景图片:', imageUrl)
        }
      }
    } catch (error) {
      console.error('处理拖拽数据失败:', error)
    }
  }
}

const handleDragLeave = (event: DragEvent) => {
  // 只有当拖拽真正离开容器时才设置isDragOver为false
  const rect = (event.currentTarget as HTMLElement).getBoundingClientRect()
  const x = event.clientX
  const y = event.clientY
  
  if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) {
    isDragOver.value = false
  }
}

// 背景图片管理
const handleSetBackground = (imageUrl: string) => {
  backgroundImageUrl.value = imageUrl
}

const handleRemoveBackground = () => {
  backgroundImageUrl.value = ''
}

// 双击移除背景
const handleDoubleClickRemove = (event: MouseEvent) => {
  if (backgroundImageUrl.value) {
    // 只有在有背景图片时才响应双击
    backgroundImageUrl.value = ''
    console.log('双击移除背景图片')
  }
}


// 语音通话所需：baseURL
const voiceBaseURL = (import.meta as any).env?.VITE_APP_BASE_API || 'http://22600428.r9.vip.cpolar.cn'

// 打字机渲染相关
const typewriterBuffer = ref('')
const isAICompleting = ref(false)
const typeIntervalMs = 20 // 每个 tick 的间隔（毫秒）
const charsPerTick = 1    // 每个 tick 输出的字符数，可按需调大
let typingTimer: number | null = null

const startTypewriter = () => {
  if (typingTimer !== null) return
  console.log('启动打字机效果')
  typingTimer = window.setInterval(() => {
    const hasBuffer = typewriterBuffer.value.length > 0
    if (hasBuffer) {
      const chunk = typewriterBuffer.value.slice(0, charsPerTick)
      typewriterBuffer.value = typewriterBuffer.value.slice(charsPerTick)
      console.log('输出字符块:', chunk, '剩余缓冲区长度:', typewriterBuffer.value.length)
      // 使用appendAIMessage进行累积追加
      messageListRef.value?.appendAIMessage(chunk)
      return
    }

    // 缓冲区清空后，如已收到完成标记，则结束本轮
    if (!hasBuffer && isAICompleting.value) {
      console.log('打字机完成，结束输出')
      // 通知完成（不再追加内容）
      messageListRef.value?.completeAIMessage('')
      isAICompleting.value = false
      if (typingTimer !== null) {
        clearInterval(typingTimer)
        typingTimer = null
      }
    }
  }, typeIntervalMs)
}

// 角色信息
import { characterInfo, chatHistory } from '@/api'
import type { RoleInfo, ChatHistoryItem } from '@/api/interface'

const role = ref<Partial<RoleInfo>>({})
const displayedName = computed(() => (role.value?.name as string) || '')
const displayedAvatar = computed(() => (role.value?.image as string) || '')
const computedTags = computed(() => (role.value.tags ? String(role.value.tags).split(',') : []))

// 背景图片样式
const backgroundImage = computed(() => {
  if (backgroundImageUrl.value) {
    return `url(${backgroundImageUrl.value})`
  }
  return ''
})

// 根据路由中的 id 请求角色详情
const fetchRoleDetail = async () => {
  const id = route.params.name as string
  if (!id) {
    return
  }
  
  // 先清空旧的角色信息，避免显示旧数据
  role.value = {}
  
  const res = await characterInfo.detail(id)
  if (res.code === 0 && res.data) {
    role.value = res.data as any
    console.log('[details] 已设置 role:', role.value)
    // 拉取历史消息
    await fetchAndRenderChatHistory()
    // 若无历史消息且有 greeting，展示招呼语
    if (messagesCount.value === 0 && role.value.greeting) {
      messageListRef.value?.startAIResponse()
      messageListRef.value?.completeAIMessage(role.value.greeting as string)
      
      // 招呼语显示后滚动到底部
      setTimeout(() => {
        const scrollContainer = document.querySelector('[data-scroll-container]')
        if (scrollContainer) {
          scrollContainer.scrollTop = scrollContainer.scrollHeight
        }
      }, 200)
    }
  } else {
    console.warn('[details] 获取角色详情失败或无数据')
  }
}

// 发送消息
const handleSendMessage = async (message: string) => {
  if (!message.trim() || isLoading.value) {
    return
  }
  
  try {
    isLoading.value = true
    
    // 添加用户消息到界面
    messageListRef.value?.addUserMessage(message)
    
    // 开始AI回复
    messageListRef.value?.startAIResponse()
    
    // 发送到后端
    await chatService.sendMessage(message)
    
  } catch (error) {
    console.error('发送消息失败:', error)
    // 显示错误消息
    messageListRef.value?.showErrorMessage('抱歉，服务暂时不可用，请稍后重试')
  } finally {
    isLoading.value = false
  }
}

// 处理重试
const handleRetry = async (messageId: string) => {
  // 重新发送最后一条用户消息
  const lastUserMessage = messageListRef.value?.getLastUserMessage()
  if (lastUserMessage) {
    await handleSendMessage(lastUserMessage.content)
  }
}

// 处理音频数据
const handleAudioData = async (audioData: ArrayBuffer) => {
  if (!(window as any).audioPlayer) {
    // 创建全局音频播放器实例
    const PcmPlayer = (await import('@/utils/pcmPlayer')).default
    ;(window as any).audioPlayer = new PcmPlayer({ sampleRate: 22050 })
  }
  ;(window as any).audioPlayer.feed(audioData)
}

// 处理SSE消息
const handleSSEMessage = (data: ChatResponse) => {
  switch (data.type) {
    case 'partial':
      // 将增量内容写入打字机缓冲，由计时器按速度输出
      if (data.content) {
        typewriterBuffer.value += data.content
        startTypewriter()
      }
      break
    case 'complete':
      // 标记完成，等缓冲区输出完后再真正 complete
      if (data.content) {
        typewriterBuffer.value += data.content
      }
      isAICompleting.value = true
      startTypewriter()
      break
    case 'imageStatus':
      // 如果需要图片，给当前打字中的消息标记占位 loading
      if (data.imageStatus?.needImage && messageListRef.value?.setCurrentMessageImageLoading) {
        messageListRef.value.setCurrentMessageImageLoading(true)
      }
      break
    case 'images':
      // 收到图片列表：取消 loading，并挂载图片数组
      if (messageListRef.value?.setCurrentMessageImages) {
        messageListRef.value.setCurrentMessageImages(Array.isArray(data.images) ? data.images : [])
      }
      break
    case 'audio':
      // 处理音频数据：使用 PcmPlayer 播放
      if (data.audioData) {
        console.log('收到音频数据，开始播放')
        handleAudioData(data.audioData)
      }
      break
    case 'error':
      // 显示具体的错误内容，比如敏感词屏蔽提示
      messageListRef.value?.showErrorMessage(data.content || '抱歉，内容不符合规范，请重新输入')
      break
    default:
      // 未标注类型时，尝试增量追加
      if ((data as any).content) {
        typewriterBuffer.value += (data as any).content
        startTypewriter()
      }
  }
}

// 处理SSE错误
const handleSSEError = (error: Event) => {
  console.error('SSE连接错误:', error)
  // 可以显示重连提示
}

// 初始化聊天
onMounted(() => {
  fetchRoleDetail()
  
  // 初始化聊天服务
  chatService.initChat(String(route.params.name))
  
  // 设置SSE回调
  chatService.onMessage(handleSSEMessage)
  chatService.onError(handleSSEError)
})

// ------- 历史对话 -------
const messagesCount = ref(0)
const renderHistory = (items: ChatHistoryItem[]) => {
  messageListRef.value?.clearMessages()
  let count = 0
  items.forEach((it) => {
    const isUser = String(it.role) === '0' || String(it.role).toLowerCase() === 'user'
    if (isUser) {
      messageListRef.value?.addUserMessage(it.content, `user_${it.id}`)
    } else {
      messageListRef.value?.addAssistantFinalMessage(it.content, `assistant_${it.id}`, undefined, it.imageUrl)
    }
    count += 1
  })
  messagesCount.value = count
  
  // 历史消息加载完成后，滚动到底部显示最新消息
  setTimeout(() => {
    const scrollContainer = document.querySelector('[data-scroll-container]')
    if (scrollContainer) {
      scrollContainer.scrollTop = scrollContainer.scrollHeight
    }
  }, 100)
}

const fetchAndRenderChatHistory = async () => {
  const id = route.params.name as string
  if (!id) return
  try {
    const res = await chatHistory.byCharacter(id)
    if (res.code === 0 && Array.isArray(res.data)) {
      renderHistory(res.data)
    } else {
      messagesCount.value = 0
    }
  } catch (e) {
    console.error('[details] 获取聊天记录失败:', e)
    messagesCount.value = 0
  }
}

// 监听路由参数变化，切换角色时刷新数据与会话
watch(() => route.params.name, async (newId, oldId) => {
  if (newId && newId !== oldId) {
    console.log('角色切换:', oldId, '->', newId)
    
    // 先清理打字机状态，避免旧角色的打字机影响新角色
    typewriterBuffer.value = ''
    isAICompleting.value = false
    if (typingTimer !== null) {
      clearInterval(typingTimer)
      typingTimer = null
    }
    
    // 重置聊天服务
    chatService.destroy()
    
    // 获取新角色数据（包含历史对话）
    await fetchRoleDetail()
    
    // 重新初始化聊天服务
    chatService.initChat(String(newId))
    chatService.onMessage(handleSSEMessage)
    chatService.onError(handleSSEError)
  }
})

// 清理资源
onUnmounted(() => {
  if (typingTimer !== null) {
    clearInterval(typingTimer)
    typingTimer = null
  }
  chatService.destroy()
})
</script>

<style scoped>
/* 聊天容器样式 */
.chat-container {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: local;
  transition: all 0.3s ease;
}

/* 拖拽时的视觉反馈 */
.chat-container.drag-over {
  background-color: rgba(99, 91, 255, 0.1);
  border: 2px dashed #635BFF;
}

/* 背景图片透明度，确保文字可读性 */
.chat-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.8);
  pointer-events: none;
  z-index: 1;
}

/* 确保消息内容在背景之上 */
.chat-container > * {
  position: relative;
  z-index: 2;
}

/* 双击提示样式 */
.chat-container {
  cursor: default;
}

.chat-container:hover::after {
  content: '双击可移除背景';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 14px;
  pointer-events: none;
  opacity: 0;
  animation: fadeInOut 2s ease-in-out;
  z-index: 10;
}

@keyframes fadeInOut {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}
</style>
